package com.lambdademo.stream;

import com.lambdademo.stream.entity.Author;
import com.lambdademo.stream.entity.Book;
import lombok.extern.slf4j.Slf4j;

import java.util.*;
import java.util.function.Consumer;
import java.util.function.Function;
import java.util.function.Predicate;
import java.util.stream.Stream;

@Slf4j
public class StreamDemo {
    public static void main(String[] args) {
        /*List<Author> authors = getAuthors();
        authors.stream()
                .distinct()
                .filter(author -> author.getAge() < 35)
                .forEach(author -> log.info("author:{}", author.getName()));*/
//        testStream();
//        testStream2();
//        testStream3();
//        testStream4();
//        testStream5();
//        testStream6();
//        testStream7();
//        testStream8();
//        testStream9();
//        testStream10();
//        testStream11();
//        testStream12();
        testStream13();
    }

    private static void testStream13() {
        // 分别获取这些作家的所出书籍的最高分和最低分并打印。
        //Stream<Author>  -> Stream<Book> ->Stream<Integer>  ->求值

        List<Author> authors = getAuthors();
        Optional<Integer> max = authors.stream()
                .flatMap(author -> author.getBooks().stream())
                .map(Book::getScore)
                .max(Comparator.comparingInt(score -> score));
        log.info("maxScore: " + max.get());
    }

    private static void testStream12() {
        //打印这些作家的所出书籍总的数目，注意删除重复元素。
        List<Author> authors = getAuthors();

        long countTotal = authors.stream()
                .flatMap(author -> author.getBooks().stream())
                .distinct()
                .count();
       log.info(String.valueOf(countTotal));

       //打印每个作家的所出书籍的数目，注意删除重复元素。
        authors.forEach(
                        author -> {
                            long count = author.getBooks().stream()
                                    .distinct()
                                    .count();
                            log.info("author:{},bookNum:{}", author.getName(), count);
                        }
                );
    }

    private static void testStream11() {
        //输出所有作家的名字
        List<Author> authors = getAuthors();

        authors.stream()
                .map(Author::getName)
                .forEach(log::info);
    }

    private static void testStream10() {
        //打印现有数据的所有分类。要求对分类进行去重。不能出现这种格式：哲学,爱情     爱情
        List<Author> authors = getAuthors();
        authors.stream()
                .flatMap(author -> author.getBooks().stream())
                .distinct()
                .flatMap(b ->  Arrays.stream(b.getCategory().split(",")))
                .distinct()
                .forEach(log::info);
    }

    private static void testStream9() {
        //打印所有书籍的名字。要求对重复的元素进行去重。
        List<Author> authors = getAuthors();

        authors.stream()
                .flatMap(author -> author.getBooks().stream())
                .distinct()
                .forEach(book -> log.info(book.getName()));

    }

    private static void testStream8() {
        //打印除了年龄最大的作家外的其他作家，要求不能有重复元素，并且按照年龄降序排序。
        List<Author> authors = getAuthors();
        authors.stream()
                .distinct()
                .sorted()
                .skip(1)
                .forEach(author -> log.info(author.getName()));
    }

    private static void testStream7() {
        //对流中的元素按照年龄进行降序排序，并且要求不能有重复的元素,然后打印其中年龄最大的两个作家的姓名。
        List<Author> authors = getAuthors();
        authors.stream()
                .distinct()
                .sorted()
                .limit(2)
                .forEach(author -> log.info(author.getName()));
    }

    private static void testStream() {
        Integer[] arr = {1, 2, 3, 4, 5, 6, 7, 8, 9};
        //Stream<Integer> stream = Arrays.stream(arr);
        Stream<Integer> stream = Stream.of(arr);
        stream.distinct().forEach(integer -> log.info("arr: {}", integer));
    }

    /**
     * 使用 Stream API 过滤并打印 map 中的特定条目
     * <p>
     * 此方法演示了如何使用 Java 8 的 Stream API 来过滤集合中的元素
     * <p>
     * 它特别专注于 map 中值大于 2 的条目，并将这些条目记录到日志中
     */
    private static void testStream2() {
        // 初始化包含一些键值对的 map
        Map<String, Integer> map = new HashMap<>();
        map.put("a", 1);
        map.put("b", 2);
        map.put("c", 3);

        // 获取 map 的条目集合并转换为 Stream
        Set<Map.Entry<String, Integer>> entrySet = map.entrySet();
        Stream<Map.Entry<String, Integer>> stream = entrySet.stream();

        // 过滤出值大于 2 的条目，并遍历打印每个条目
        stream.filter(mapEntry -> mapEntry.getValue() > 2)
                .forEach(mapEntry -> log.info("mapEntry: {}", mapEntry));
    }

    private static void testStream3() {
        List<Author> authors = getAuthors();
//        打印所有姓名长度大于1的作家的姓名
        authors.stream()
                .filter(author -> author.getName().length() > 2)
                .forEach(author -> log.info(author.getName()));
    }

    private static void testStream4() {
        /*//        打印所有作家的姓名
        List<Author> authors = getAuthors();

        // 获取所有作家的姓名,转换
        authors.stream()
                .map(author -> author.getName())
                .forEach(s -> log.info(s));

        // 计算，年龄加10
        authors.stream()
                .map(Author::getAge)
                .map(age->age+10)
                .forEach(age-> log.info(String.valueOf(age)));*/
        List<Author> authors = getAuthors();
        authors.stream()
                .distinct()
                .filter(author -> author.getAge() < 35)
                .map(Author::getName)
                .forEach(log::info);
    }

    private static void testStream5() {
//      打印所有作家的姓名，并且要求其中不能有重复元素。
        List<Author> authors = getAuthors();
        authors.stream()
                .distinct()
                .forEach(author -> log.info(author.getName()));
    }

    private static void testStream6() {
        List<Author> authors = getAuthors();
//        对流中的元素按照年龄进行降序排序，并且要求不能有重复的元素。
        authors.stream()
                .distinct()
                .sorted((o1, o2) -> o1.getAge() - o2.getAge())
                .forEach(author -> log.info(author.getName() + ": " + author.getAge()));
    }

    private static List<Author> getAuthors() {
        //数据初始化
        Author author = new Author(1L, "蒙多", 33, "一个从菜鸟到 become 的java程序员", null);
        Author author2 = new Author(2L, "白居易", 25, "白居易的描述信息", null);
        Author author3 = new Author(3L, "王安石", 35, "王安石的描述信息", null);
        Author author4 = new Author(4L, "李白", 45, "李白的描述信息", null);

        //书籍列表
        List<Book> books1 = new ArrayList<>();
        List<Book> books2 = new ArrayList<>();
        List<Book> books3 = new ArrayList<>();

        books1.add(new Book(1L, "Spring Boot 快速教程", "Spring Boot", 89, "一个从入门到放弃的 Spring Boot 教程"));
        books1.add(new Book(2L, "Spring Boot 快速教程2", "Spring Boot", 89, "一个从入门到放弃的 Spring Boot 教程"));

        books2.add(new Book(3L, "Spring Cloud 快速教程", "Spring Cloud", 79, "一个从入门到放弃的 Spring Cloud 教程"));
        books2.add(new Book(4L, "Spring Cloud 快速教程2", "Spring Cloud2", 99, "一个从入门到放弃的 Spring Cloud 教程2"));
        books2.add(new Book(5L, "Spring Cloud 快速教程3", "Spring Cloud3", 99, "一个从入门到放弃的 Spring Cloud 教程3"));

        books3.add(new Book(6L, "Spring Cloud 教程", "Spring Cloud", 99, "一个从入门到放弃的 Spring Cloud 教程"));
        books3.add(new Book(7L, "Spring Cloud 教程2", "Spring Cloud2", 99, "一个从入门到放弃的 Spring Cloud 教程2"));
        books3.add(new Book(8L, "Spring Cloud 教程3", "Spring Cloud3", 99, "一个从入门到放弃的 Spring Cloud 教程3"));

        author.setBooks(books1);
        author2.setBooks(books2);
        author3.setBooks(books3);
        author4.setBooks(books3);

        return new ArrayList<>(Arrays.asList(author, author2, author3, author4));
    }
}
